home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Game / misc / WormWars.lha / WormWars / Source / le.c < prev    next >
C/C++ Source or Header  |  2004-08-22  |  35KB  |  997 lines

  1. // 1. INCLUDES -----------------------------------------------------------
  2.  
  3. #include <exec/types.h>
  4. #include <exec/memory.h>
  5. #include <exec/alerts.h>
  6.  
  7. #include "diff.h"
  8. #include "same.h"
  9. #include "amiga.h"
  10.  
  11. #include <intuition/intuition.h> // for struct Window, etc.
  12. #include <libraries/gadtools.h>  // for GT_VisualInfo, etc.
  13.  
  14. #include <clib/exec_protos.h>
  15. #include <clib/graphics_protos.h>
  16. #include <clib/intuition_protos.h>
  17. #include <clib/gadtools_protos.h>
  18.  
  19. #include <stdlib.h>              // for EXIT_SUCCESS, etc.
  20.  
  21. // 2. DEFINES ------------------------------------------------------------
  22.  
  23. #define ALTJUMP         5
  24.  
  25. /* pseudo-gadgets */
  26. #define PSEUDOGADGETS   8    // counting from 1
  27. #define GADGETX         (-2) // negatives must be within parentheses
  28. #define EMPTYGADGET    ((fieldy / 2) - 7)
  29. #define SILVERGADGET   ((fieldy / 2) - 5)
  30. #define GOLDGADGET     ((fieldy / 2) - 3)
  31. #define DYNAMITEGADGET ((fieldy / 2) - 1)
  32. #define WOODGADGET     ((fieldy / 2) + 1)
  33. #define STONEGADGET    ((fieldy / 2) + 3)
  34. #define METALGADGET    ((fieldy / 2) + 5)
  35. #define FROSTGADGET    ((fieldy / 2) + 7)
  36.  
  37. // 3. EXPORTED VARIABLES -------------------------------------------------
  38.  
  39. // 4. IMPORTED VARIABLES -------------------------------------------------
  40.  
  41. IMPORT struct Window*        MainWindowPtr;
  42. IMPORT struct Menu*          MenuPtr;
  43. IMPORT struct VisualInfo*    VisualInfoPtr;
  44. IMPORT struct timerequest*   TimerRqPtr;
  45. IMPORT struct InputEvent     GameEvent;
  46. IMPORT struct Screen*        ScreenPtr;
  47.  
  48. IMPORT ABOOL               anims,
  49.                            clearthem,
  50.                            engraved,
  51.                            icons,
  52.                            modified,
  53.                            titlebar;
  54. IMPORT SBYTE               a,
  55.                            board[MAXLEVELS + 1][MINFIELDX + 1][MINFIELDY + 1],
  56.                            startx[MAXLEVELS + 1],
  57.                            starty[MAXLEVELS + 1],
  58.                            level, levels;
  59. IMPORT SWORD               fieldx, fieldy;
  60.  
  61. // 5. MODULE VARIABLES ---------------------------------------------------
  62.  
  63. MODULE ABOOL               sticky = FALSE;
  64. MODULE UBYTE               brush  = STONE;
  65. MODULE SBYTE               fex    = MINFIELDX / 2,
  66.                            fey    = MINFIELDY / 2;
  67.  
  68. #ifdef LATTICE
  69.     MODULE UWORD chip CustomPointer[] =
  70. #endif
  71. #ifdef __STORM__
  72.     __chip UWORD CustomPointer[] =
  73. #endif
  74.  
  75. {   0x0000, 0x0000, /* reserved */
  76.  
  77.     0xF800, 0xFC00, /* 1st row 1st plane, 1st row 2nd plane */
  78.     0xF800, 0x8400, /* 2nd row 1st plane, 2nd row 2nd plane */
  79.     0xF800, 0x8400, /* 3rd row 1st plane, 3rd row 2nd plane */
  80.     0xF800, 0x8400, /* 4th row 1st plane, 4th row 2nd plane */
  81.     0xF800, 0x8400, /* 5th row 1st plane, 5th row 2nd plane */
  82.     0x8000, 0xFC00, /* 6th row 1st plane, 6th row 2nd plane */
  83.  
  84.     0x0000, 0x0000  /* reserved */
  85.  
  86. /*  11111000-------- 11111100--------
  87.     11111000-------- 10000100--------
  88.     11111000-------- 10000100--------
  89.     11111000-------- 10000100--------
  90.     11111000-------- 10000100--------
  91.     10000000-------- 11111100-------- */
  92.  
  93. };
  94.  
  95. // 6. MODULE STRUCTURES --------------------------------------------------
  96.  
  97. // 7. MODULE FUNCTIONS ---------------------------------------------------
  98.  
  99. MODULE void undot(void);
  100. MODULE void stamp(UBYTE square);
  101. MODULE void fillfield(UBYTE which);
  102. MODULE void underline(UBYTE square);
  103. MODULE SBYTE oldxpixeltosquare(SWORD x);
  104. MODULE SBYTE oldypixeltosquare(SWORD y);
  105. MODULE SBYTE xpixeltosquare(SWORD x);
  106. MODULE SBYTE ypixeltosquare(SWORD y);
  107. MODULE void levelappend(void);
  108. MODULE void leveldelete(void);
  109. MODULE void levelerase(void);
  110. MODULE void levelinsert(void);
  111. MODULE void copyfield(UBYTE source, UBYTE destination);
  112. MODULE SBYTE fexwrap(SBYTE x);
  113. MODULE SBYTE feywrap(SBYTE y);
  114.  
  115. // 8. CODE ---------------------------------------------------------------
  116.  
  117. AGLOBAL void fieldedit(void)
  118. {   AUTO    ABOOL                leftdown  = FALSE,
  119.                                  timer     = FALSE;
  120.     AUTO    SBYTE                pointerx, pointery,
  121.                                  which,
  122.                                  x, y;
  123.     AUTO    SWORD                mousex, mousey;
  124.     AUTO    UWORD                code, qual;
  125.     AUTO    ULONG                class;
  126.     AUTO    struct IntuiMessage* MsgPtr;
  127.     AUTO    struct MenuItem*     ItemPtr;
  128.     PERSIST ABOOL                clipboarded = FALSE;
  129.     PERSIST UBYTE                clipboard[MINFIELDX + 1][MINFIELDY + 1];
  130.  
  131.     if (level > levels)
  132.         level = levels;
  133.     OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  134.     if (!clipboarded)
  135.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  136.  
  137.     /* draw pseudo-gadgets */
  138.  
  139.     clearscreen();
  140.     for (which = 0; which < PSEUDOGADGETS; which++)
  141.     {   DrawBevelBox
  142.         (   MainWindowPtr->RPort,
  143.             STARTXPIXEL - (SQUAREX * 2) - 4,
  144.             FIELDCENTREY - (SQUAREY * (PSEUDOGADGETS - 1)) + (which * 2 * SQUAREY) - 4,
  145.             SQUAREX + 8,
  146.             SQUAREY + 8,
  147.             GT_VisualInfo, VisualInfoPtr,
  148.             TAG_DONE
  149.         );
  150.     }
  151.     SetAPen(MainWindowPtr->RPort, WHITE);
  152.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   EMPTYGADGET * SQUAREY));
  153.     Text(MainWindowPtr->RPort, "F1:", 3);
  154.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (  SILVERGADGET * SQUAREY));
  155.     Text(MainWindowPtr->RPort, "F2:", 3);
  156.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (    GOLDGADGET * SQUAREY));
  157.     Text(MainWindowPtr->RPort, "F3:", 3);
  158.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (DYNAMITEGADGET * SQUAREY));
  159.     Text(MainWindowPtr->RPort, "F4:", 3);
  160.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (    WOODGADGET * SQUAREY));
  161.     Text(MainWindowPtr->RPort, "F5:", 3);
  162.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   STONEGADGET * SQUAREY));
  163.     Text(MainWindowPtr->RPort, "F6:", 3);
  164.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   METALGADGET * SQUAREY));
  165.     Text(MainWindowPtr->RPort, "F7:", 3);
  166.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   FROSTGADGET * SQUAREY));
  167.     Text(MainWindowPtr->RPort, "F8:", 3);
  168.  
  169.     draw(GADGETX,    EMPTYGADGET,    EMPTY);
  170.     draw(GADGETX,   SILVERGADGET,   SILVER);
  171.     draw(GADGETX,     GOLDGADGET,     GOLD);
  172.     draw(GADGETX, DYNAMITEGADGET, DYNAMITE);
  173.     draw(GADGETX,     WOODGADGET,     WOOD);
  174.     draw(GADGETX,    STONEGADGET,    STONE);
  175.     draw(GADGETX,    METALGADGET,    METAL);
  176.     draw(GADGETX,    FROSTGADGET,    FROST);
  177.  
  178.     SetAPen(MainWindowPtr->RPort, BLACK);
  179.     RectFill
  180.     (   MainWindowPtr->RPort,
  181.         STARTXPIXEL - 5,
  182.         STARTYPIXEL + (fieldy * SQUAREY / 2) - (7 * SQUAREY) - 7,
  183.         STARTXPIXEL - 3,
  184.         STARTYPIXEL + (fieldy * SQUAREY / 2) + (7 * SQUAREY) + 7
  185.     );
  186.  
  187.     underline(brush);
  188.     turborender();
  189.     say("", BLACK);
  190.     saylevel(WHITE);
  191.     clearkybd();
  192.  
  193.     if (!valid(fex, fey))
  194.     {   fex = startx[level];
  195.         fey = starty[level];
  196.     }
  197.     dot();
  198.  
  199.     if (!(ModifyIDCMP(MainWindowPtr, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | IDCMP_REFRESHWINDOW | IDCMP_MOUSEMOVE)))
  200.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  201.         cleanexit(EXIT_FAILURE);
  202.     }
  203.  
  204.     playsong(2);
  205.  
  206.     while (a == FIELDEDIT)
  207.     {   Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  208.         while (MsgPtr = GT_GetIMsg(MainWindowPtr->UserPort))
  209.         {   class  = MsgPtr->Class;
  210.             code   = MsgPtr->Code;
  211.             qual   = MsgPtr->Qualifier;
  212.             mousex = MsgPtr->MouseX;
  213.             mousey = MsgPtr->MouseY;
  214.             if (class == IDCMP_MENUVERIFY && code == MENUHOT)
  215.             {   if
  216.                 (   mousex >= STARTXPIXEL
  217.                  && mousex <=   ENDXPIXEL
  218.                  && mousey >= STARTYPIXEL
  219.                  && mousey <=   ENDYPIXEL
  220.                  && !(qual & IEQUALIFIER_RCOMMAND)
  221.                 )
  222.                 {   MsgPtr->Code = MENUCANCEL;
  223.             }   }
  224.             GT_ReplyIMsg(MsgPtr);
  225.             switch (class)
  226.             {
  227.             case IDCMP_MOUSEMOVE:
  228.                 if (leftdown)
  229.                 {   pointerx = xpixeltosquare(mousex);
  230.                     pointery = ypixeltosquare(mousey);
  231.                     if
  232.                     (   (pointerx != fex || pointery != fey)
  233.                      && valid(pointerx, pointery)
  234.                     )
  235.                     {   undot();
  236.                         fex = pointerx;
  237.                         fey = pointery;
  238.                         stamp(brush);
  239.                 }   }
  240.             break;
  241.             case IDCMP_MENUPICK:
  242.                 while (code != MENUNULL)
  243.                 {   ItemPtr = ItemAddress(MenuPtr, code);
  244.                     switch (MENUNUM(code))
  245.                     {
  246.                     case MN_PROJECT:
  247.                         switch (ITEMNUM(code))
  248.                         {
  249.                         case IN_NEW:
  250.                             newfields();
  251.                             say("New done.", WHITE);
  252.                         break;
  253.                         case IN_OPEN:
  254.                             fileopen(FALSE);
  255.                         break;
  256.                         case IN_REVERT:
  257.                             fileopen(TRUE);
  258.                         break;
  259.                         case IN_SAVE:
  260.                             if (modified)
  261.                             {   clearhiscores();
  262.                                 modified = FALSE;
  263.                             }
  264.                             filesaveas(FALSE);
  265.                             turborender();
  266.                         break;
  267.                         case IN_SAVEAS:
  268.                             if (modified)
  269.                             {   clearhiscores();
  270.                                 modified = FALSE;
  271.                             }
  272.                             filesaveas(TRUE);
  273.                             turborender();
  274.                         break;
  275.                         case IN_PROJECTDELETE:
  276.                             filedelete();
  277.                         break;
  278.                         case IN_QUIT:
  279.                             if (verify())
  280.                                 cleanexit(EXIT_SUCCESS);
  281.                         break;
  282.                         default:
  283.                         break;
  284.                         }
  285.                     break;
  286.                     case MN_EDIT:
  287.                         switch (ITEMNUM(code))
  288.                         {
  289.                         case IN_CUT:
  290.                             for (x = 0; x <= MINFIELDX; x++)
  291.                                 for (y = 0; y <= MINFIELDY; y++)
  292.                                     clipboard[x][y] = board[level][x][y];
  293.                             leveldelete();
  294.                             clipboarded = TRUE;
  295.                             modified = TRUE;
  296.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  297.                         break;
  298.                         case IN_COPY:
  299.                             for (x = 0; x <= MINFIELDX; x++)
  300.                                 for (y = 0; y <= MINFIELDY; y++)
  301.                                     clipboard[x][y] = board[level][x][y];
  302.                             clipboarded = TRUE;
  303.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  304.                         break;
  305.                         case IN_PASTE:
  306.                             for (x = 0; x <= MINFIELDX; x++)
  307.                                 for (y = 0; y <= MINFIELDY; y++)
  308.                                     board[level][x][y] = clipboard[x][y];
  309.                             turborender();
  310.                             modified = TRUE;
  311.                         break;
  312.                         case IN_ERASE:
  313.                             levelerase();
  314.                         break;
  315.                         case IN_INSERT:
  316.                             levelinsert();
  317.                         break;
  318.                         case IN_EDITDELETE:
  319.                             leveldelete();
  320.                         break;
  321.                         case IN_APPEND:
  322.                             levelappend();
  323.                         break;
  324.                         default:
  325.                         break;
  326.                         }
  327.                     break;
  328.                     case MN_SETTINGS:
  329.                         switch(ITEMNUM(code))
  330.                         {
  331.                         case IN_ANIMATIONS:
  332.                             if (ItemPtr->Flags & CHECKED)
  333.                             {   anims = TRUE;
  334.                             } else
  335.                             {   anims = FALSE;
  336.                             }
  337.                         break;
  338.                         case IN_CREATEICONS:
  339.                             if (ItemPtr->Flags & CHECKED)
  340.                             {   icons = TRUE;
  341.                             } else
  342.                             {   icons = FALSE;
  343.                             }
  344.                         break;
  345.                         case IN_ENGRAVEDSQUARES:
  346.                             if (ItemPtr->Flags & CHECKED)
  347.                             {   engraved = TRUE;
  348.                             } else
  349.                             {   engraved = FALSE;
  350.                             }
  351.                         break;
  352.                         case IN_SHOWTITLEBAR:
  353.                             if (ItemPtr->Flags & CHECKED)
  354.                             {   titlebar = TRUE;
  355.                             } else
  356.                             {   titlebar = FALSE;
  357.                             }
  358.                             ShowTitle(ScreenPtr, titlebar);
  359.                         break;
  360.                         default:
  361.                         break;
  362.                         }
  363.                     break;
  364.                     case MN_HELP:
  365.                         switch(ITEMNUM(code))
  366.                         {
  367.                         case IN_CREATURES:
  368.                             help(ORB);
  369.                         break;
  370.                         case IN_OBJECTS:
  371.                             help(AFFIXER);
  372.                         break;
  373.                         case IN_ABOUT:
  374.                             helpabout();
  375.                         break;
  376.                         default:
  377.                         break;
  378.                         }
  379.                     break;
  380.                     default:
  381.                     break;
  382.                     } // hctiws
  383.                     code = ItemPtr->NextSelect;
  384.                 } // elihw
  385.             break;
  386.             case IDCMP_RAWKEY:
  387.                 if (!(qual & IEQUALIFIER_REPEAT))
  388.                 {   effect(FXCLICK);
  389.                 }
  390.                 switch(code)
  391.                 {
  392.                 case DELETE:
  393.                     if (!(qual & IEQUALIFIER_REPEAT))
  394.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  395.                             level = 1;
  396.                         elif (--level < 0)
  397.                             level = levels;
  398.                         saylevel(WHITE);
  399.                         turborender();
  400.                     }
  401.                 break;
  402.                 case HELP:
  403.                     if (!(qual & IEQUALIFIER_REPEAT))
  404.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  405.                             level = levels;
  406.                         elif (++level > levels)
  407.                             level = 0;
  408.                         saylevel(WHITE);
  409.                         turborender();
  410.                     }
  411.                 break;
  412.                 case M:
  413.                     if (!(qual & IEQUALIFIER_REPEAT))
  414.                         toggle(M);
  415.                 break;
  416.                 case F:
  417.                     if (!(qual & IEQUALIFIER_REPEAT))
  418.                         toggle(F);
  419.                 break;
  420.                 case ESCAPE:
  421.                     if (!(qual & IEQUALIFIER_REPEAT))
  422.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  423.                         {   if (verify())
  424.                             {   cleanexit(EXIT_SUCCESS);
  425.                         }   }
  426.                         else
  427.                         {   a = GAMEOVER;
  428.                     }   }
  429.                 break;
  430.                 case SPACEBAR:
  431.                 case RETURN:
  432.                 case ENTER:
  433.                     if (!(qual & IEQUALIFIER_REPEAT))
  434.                         a = GAMEOVER;
  435.                 break;
  436.                 case NUMERICOPEN:
  437.                 case COMMA:
  438.                     underline(255);
  439.  
  440.                     if (brush > 0)
  441.                     {   brush--;
  442.                     } else
  443.                     {   brush = LASTOBJECT; // note sign issues
  444.                     }
  445.                     stamp(brush);
  446.                 break;
  447.                 case NUMERICCLOSE:
  448.                 case ALPHADOT:
  449.                     underline(255);
  450.  
  451.                     if (brush < LASTOBJECT)
  452.                     {   brush++;
  453.                     } else
  454.                     {   brush = 0;
  455.                     }
  456.                     stamp(brush);
  457.                 break;
  458.                 case C:
  459.                     effect(FXUSE_TELEPORT); /* interesting */
  460.                     undot();
  461.                     fex = MINFIELDX / 2;
  462.                     fey = MINFIELDY / 2;
  463.                     dot();
  464.                 break;
  465.                 case S:
  466.                     stamp(START);
  467.                 break;
  468.                 case KEY_U:
  469.                     stamp(ARROWUP);
  470.                 break;
  471.                 case D:
  472.                     stamp(ARROWDOWN);
  473.                 break;
  474.                 case ALPHAONE:
  475.                     stamp(EMPTY);
  476.                 break;
  477.                 case ALPHATWO:
  478.                     stamp(SILVER);
  479.                 break;
  480.                 case ALPHATHREE:
  481.                     stamp(GOLD);
  482.                 break;
  483.                 case ALPHAFOUR:
  484.                     stamp(DYNAMITE);
  485.                 break;
  486.                 case ALPHAFIVE:
  487.                     stamp(WOOD);
  488.                 break;
  489.                 case ALPHASIX:
  490.                     stamp(STONE);
  491.                 break;
  492.                 case ALPHASEVEN:
  493.                     stamp(METAL);
  494.                 break;
  495.                 case ALPHAEIGHT:
  496.                     stamp(FROST);
  497.                 break;
  498.                 case F1:
  499.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  500.                     {   fillfield(EMPTY);
  501.                     } else setbrush(EMPTY);
  502.                 break;
  503.                 case F2:
  504.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  505.                     {   fillfield(SILVER);
  506.                     } else setbrush(SILVER);
  507.                 break;
  508.                 case F3:
  509.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  510.                     {   fillfield(GOLD);
  511.                     } else setbrush(GOLD);
  512.                 break;
  513.                 case F4:
  514.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  515.                     {   fillfield(DYNAMITE);
  516.                     } else setbrush(DYNAMITE);
  517.                 break;
  518.                 case F5:
  519.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  520.                     {   fillfield(WOOD);
  521.                     } else setbrush(WOOD);
  522.                 break;
  523.                 case F6:
  524.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  525.                     {   fillfield(STONE);
  526.                     } else setbrush(STONE);
  527.                 break;
  528.                 case F7:
  529.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  530.                     {   fillfield(METAL);
  531.                     } else setbrush(METAL);
  532.                 break;
  533.                 case F8:
  534.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  535.                     {   fillfield(FROST);
  536.                     } else setbrush(FROST);
  537.                 break;
  538.                 case NUMERICZERO:
  539.                     if (!(qual & IEQUALIFIER_REPEAT))
  540.                     {   if (!sticky)
  541.                         {   sticky = TRUE;
  542.                             say("Sticky mode on", WHITE);
  543.                             stamp(brush);
  544.                         } else
  545.                         {   sticky = FALSE;
  546.                             say("Sticky mode off", WHITE);
  547.                             dot();
  548.                     }   }
  549.                 break;
  550.                 case NUMERICDOT:
  551.                     stamp(brush);
  552.                 break;
  553.                 case KEY_X:
  554.                     undot();
  555.                     fex = MINFIELDX - fex;
  556.                     dot();
  557.                 break;
  558.                 case KEY_Y:
  559.                     undot();
  560.                     fey = MINFIELDY - fey;
  561.                     dot();
  562.                 break;
  563.                 case NUMERICFOUR:
  564.                 case LEFT:
  565.                     undot();
  566.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  567.                     {   fex = 0;
  568.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  569.                     {   fex = fexwrap(fex - ALTJUMP);
  570.                     } else
  571.                     {   fex = fexwrap(fex - 1);
  572.                     }
  573.                     if (sticky)
  574.                     {   stamp(brush);
  575.                     } else
  576.                     {   dot();
  577.                     }
  578.                 break;
  579.                 case NUMERICSIX:
  580.                 case RIGHT:
  581.                     undot();
  582.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  583.                     {   fex = MINFIELDX;
  584.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  585.                     {   fex = fexwrap(fex + ALTJUMP);
  586.                     } else
  587.                     {   fex = fexwrap(fex + 1);
  588.                     }
  589.                     if (sticky)
  590.                     {   stamp(brush);
  591.                     } else
  592.                     {   dot();
  593.                     }
  594.                 break;
  595.                 case NUMERICEIGHT:
  596.                 case UP:
  597.                     undot();
  598.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  599.                     {   fey = 0;
  600.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  601.                     {   fey = feywrap(fey - ALTJUMP);
  602.                     } else
  603.                     {   fey = feywrap(fey - 1);
  604.                     }
  605.                     if (sticky)
  606.                     {   stamp(brush);
  607.                     } else
  608.                     {   dot();
  609.                     }
  610.                 break;
  611.                 case NUMERICFIVE:
  612.                 case NUMERICTWO:
  613.                 case DOWN:
  614.                     undot();
  615.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  616.                     {   fey = MINFIELDY;
  617.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  618.                     {   fey = feywrap(fey + ALTJUMP);
  619.                     } else
  620.                     {   fey = feywrap(fey + 1);
  621.                     }
  622.                     if (sticky)
  623.                     {   stamp(brush);
  624.                     } else
  625.                     {   dot();
  626.                     }
  627.                 break;
  628.                 case NUMERICSEVEN:
  629.                     undot();
  630.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  631.                     {   fex = 0;
  632.                         fey = 0;
  633.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  634.                     {   fex = fexwrap(fex - ALTJUMP);
  635.                         fey = feywrap(fey - ALTJUMP);
  636.                     } else
  637.                     {   fex = fexwrap(fex - 1);
  638.                         fey = feywrap(fey - 1);
  639.                     }
  640.                     if (sticky)
  641.                     {   stamp(brush);
  642.                     } else
  643.                     {   dot();
  644.                     }
  645.                 break;
  646.                 case NUMERICNINE:
  647.                     undot();
  648.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  649.                     {   fex = MINFIELDX;
  650.                         fey = 0;
  651.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  652.                     {   fex = fexwrap(fex + ALTJUMP);
  653.                         fey = feywrap(fey - ALTJUMP);
  654.                     } else
  655.                     {   fex = fexwrap(fex + 1);
  656.                         fey = feywrap(fey - 1);
  657.                     }
  658.                     if (sticky)
  659.                     {   stamp(brush);
  660.                     } else
  661.                     {   dot();
  662.                     }
  663.                 break;
  664.                 case NUMERICONE:
  665.                     undot();
  666.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  667.                     {   fex = 0;
  668.                         fey = MINFIELDY;
  669.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  670.                     {   fex = fexwrap(fex - ALTJUMP);
  671.                         fey = feywrap(fey + ALTJUMP);
  672.                     } else
  673.                     {   fex = fexwrap(fex - 1);
  674.                         fey = feywrap(fey + 1);
  675.                     }
  676.                     if (sticky)
  677.                     {   stamp(brush);
  678.                     } else
  679.                     {   dot();
  680.                     }
  681.                 break;
  682.                 case NUMERICTHREE:
  683.                     undot();
  684.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  685.                     {   fex = MINFIELDX;
  686.                         fey = MINFIELDY;
  687.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  688.                     {   fex = fexwrap(fex + ALTJUMP);
  689.                         fey = feywrap(fey + ALTJUMP);
  690.                     } else
  691.                     {   fex = fexwrap(fex + 1);
  692.                         fey = feywrap(fey + 1);
  693.                     }
  694.                     if (sticky)
  695.                     {   stamp(brush);
  696.                     } else
  697.                     {   dot();
  698.                     }
  699.                 break;
  700.                 default:
  701.                 break;
  702.                 } // hctiws
  703.             break;
  704.             case IDCMP_MOUSEBUTTONS:
  705.                 if (code == SELECTDOWN)
  706.                 {   pointerx = oldxpixeltosquare(mousex);
  707.                     pointery = oldypixeltosquare(mousey);
  708.                     leftdown = TRUE;
  709.                     if (pointerx == GADGETX)
  710.                     {   if (pointery == GOLDGADGET)
  711.                             setbrush(GOLD);
  712.                         elif (pointery == SILVERGADGET)
  713.                             setbrush(SILVER);
  714.                         elif (pointery == EMPTYGADGET)
  715.                             setbrush(EMPTY);
  716.                         elif (pointery == WOODGADGET)
  717.                             setbrush(WOOD);
  718.                         elif (pointery == DYNAMITEGADGET)
  719.                             setbrush(DYNAMITE);
  720.                         elif (pointery == STONEGADGET)
  721.                             setbrush(STONE);
  722.                         elif (pointery == METALGADGET)
  723.                             setbrush(METAL);
  724.                         elif (pointery == FROSTGADGET)
  725.                             setbrush(FROST);
  726.                     } else
  727.                     {   pointerx = xpixeltosquare(mousex);
  728.                         pointery = ypixeltosquare(mousey);
  729.                         if (valid(pointerx, pointery))
  730.                         {   undot();
  731.                             fex = pointerx;
  732.                             fey = pointery;
  733.                             stamp(brush);
  734.                 }   }   }
  735.                 elif (code == SELECTUP)
  736.                 {   leftdown = FALSE;
  737.                 } elif (code == MENUUP)
  738.                 {   pointerx = xpixeltosquare(mousex);
  739.                     pointery = ypixeltosquare(mousey);
  740.                     if (valid(pointerx, pointery))
  741.                     {   undot();
  742.                         fex = pointerx;
  743.                         fey = pointery;
  744.                         stamp(EMPTY);
  745.                 }   }
  746.             break;
  747.             case IDCMP_CLOSEWINDOW:
  748.                 cleanexit(EXIT_SUCCESS);
  749.             break;
  750.             case IDCMP_REFRESHWINDOW:
  751.                 GT_BeginRefresh(MainWindowPtr);
  752.                 GT_EndRefresh(MainWindowPtr, TRUE);
  753.             break;
  754.             default:
  755.                 /* IDCMP_MENUVERIFY, IDCMP_INTUITICKS, IDCMP_ACTIVEWINDOW */
  756.             break;
  757.     }   }   }
  758.  
  759.     /* exit to title screen */
  760.  
  761.     if (!(ModifyIDCMP(MainWindowPtr, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS)))
  762.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  763.     cleanexit(EXIT_FAILURE);
  764.     }
  765.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  766.     if (timer)
  767.     {   AbortIO((struct IORequest *) TimerRqPtr);
  768.          WaitIO((struct IORequest *) TimerRqPtr);
  769.     }
  770.     if (clearthem)
  771.         clearhiscores();
  772. }
  773.  
  774. MODULE void stamp(UBYTE square)
  775. {   if (square == START)
  776.     {   fedraw(startx[level], starty[level], EMPTY);
  777.         board[level][startx[level]][starty[level]] = EMPTY;
  778.         startx[level] = fex;
  779.         starty[level] = fey;
  780.         board[level][fex][fey] = EMPTY;
  781.     } else
  782.     {   board[level][fex][fey] = square;
  783.     }
  784.  
  785.     fedraw(fex, fey, square);
  786.     dot();
  787.     modified = clearthem = TRUE;
  788. }
  789.  
  790. MODULE void undot(void)
  791. {   if (startx[level] == fex && starty[level] == fey)
  792.         fedraw(fex, fey, START);
  793.     else fedraw(fex, fey, board[level][fex][fey]);
  794. }
  795.  
  796. MODULE void fillfield(UBYTE which)
  797. {   SBYTE x, y;
  798.  
  799.     // Service routine for level editor.
  800.  
  801.     for (x = 0; x <= MINFIELDX; x++)
  802.     {   for (y = 0; y <= MINFIELDY; y++)
  803.         {   board[level][x][y] = which;
  804.             fedraw(x, y, which);
  805.     }   }
  806.     board[level][startx[level]][starty[level]] = EMPTY;
  807.     fedraw(startx[level], starty[level], START);
  808.     dot();
  809. }
  810.  
  811. AGLOBAL void setbrush(UBYTE newbrush)
  812. {   brush = newbrush;
  813.     underline(brush);
  814. }
  815.  
  816. MODULE void underline(UBYTE square)
  817. {   /* Removes old underline, draws new underline.
  818.  
  819.     square: which square-type to underline, or 255 for clear only.
  820.     Squares which do not correspond to any pseudo-gadgets
  821.     (eg. objects) are converted to 255s. */
  822.  
  823.     PERSIST SWORD oldy = 255;
  824.     AUTO    SWORD y;
  825.  
  826.     switch(square)
  827.     {
  828.     case EMPTY:
  829.         y = STARTYPIXEL + (EMPTYGADGET * SQUAREY);
  830.     break;
  831.     case SILVER:
  832.         y = STARTYPIXEL + (SILVERGADGET * SQUAREY);
  833.     break;
  834.     case GOLD:
  835.         y = STARTYPIXEL + (GOLDGADGET * SQUAREY);
  836.     break;
  837.     case DYNAMITE:
  838.         y = STARTYPIXEL + (DYNAMITEGADGET * SQUAREY);
  839.     break;
  840.     case WOOD:
  841.         y = STARTYPIXEL + (WOODGADGET * SQUAREY);
  842.     break;
  843.     case STONE:
  844.         y = STARTYPIXEL + (STONEGADGET * SQUAREY);
  845.     break;
  846.     case METAL:
  847.         y = STARTYPIXEL + (METALGADGET * SQUAREY);
  848.     break;
  849.     case FROST:
  850.         y = STARTYPIXEL + (FROSTGADGET * SQUAREY);
  851.     break;
  852.     default:
  853.         square = 255;
  854.         y = 0; // to avoid spurious warnings
  855.     break;
  856.     }
  857.  
  858.     if (oldy != 255)
  859.     {   SetAPen(MainWindowPtr->RPort, BLACK);
  860.         Move(MainWindowPtr->RPort, STARTXPIXEL - 4, oldy);
  861.         Draw(MainWindowPtr->RPort, STARTXPIXEL - 4, oldy + SQUAREY);
  862.     }
  863.     if (square != 255)
  864.     {   SetAPen(MainWindowPtr->RPort, WHITE);
  865.         Move(MainWindowPtr->RPort, STARTXPIXEL - 4, y);
  866.         Draw(MainWindowPtr->RPort, STARTXPIXEL - 4, y + SQUAREY);
  867.         oldy = y;
  868. }   }
  869.  
  870. AGLOBAL void dot(void)
  871. {   SWORD x, xx, y, yy;
  872.  
  873.     /* Squares are dotted as follows:
  874.  
  875.          012345678901
  876.         0............
  877.         1............
  878.         2............
  879.         3............
  880.         4....WWW.....
  881.         5....WWWB....
  882.         6....WWWB....
  883.         7.....BBB....
  884.         8............
  885.         9............
  886.        10............
  887.        11............ */
  888.  
  889.         xx = ((fex + LEFTGAP) * SQUAREX) + STARTXPIXEL;
  890.         yy = ((fey +  TOPGAP) * SQUAREY) + STARTYPIXEL;
  891.  
  892.     if (sticky)
  893.         SetAPen(MainWindowPtr->RPort, RED);
  894.     else SetAPen(MainWindowPtr->RPort, WHITE);
  895.         for (x = 4; x <= 6; x++)
  896.         {   for (y = 4; y <= 6; y++)
  897.             {   WritePixel(MainWindowPtr->RPort, xx + x, yy + y);
  898.         }   }
  899.         SetAPen(MainWindowPtr->RPort, BLACK);
  900.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 5);
  901.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 6);
  902.         WritePixel(MainWindowPtr->RPort, xx + 5, yy + 7);
  903.         WritePixel(MainWindowPtr->RPort, xx + 6, yy + 7);
  904.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 7);
  905. }
  906.  
  907. MODULE SBYTE oldxpixeltosquare(SWORD x)
  908. {   x = (x - STARTXPIXEL) / SQUAREX;
  909.     if (x < 0)
  910.         x--;
  911.     return ((SBYTE) x);
  912. }
  913. MODULE SBYTE oldypixeltosquare(SWORD y)
  914. {   y = (y - STARTYPIXEL) / SQUAREY;
  915.     if (y < 0)
  916.         y--;
  917.     return ((SBYTE) y);
  918. }
  919. MODULE SBYTE xpixeltosquare(SWORD x)
  920. {   x = ((x - STARTXPIXEL) / SQUAREX) - LEFTGAP;
  921.     if (x < 0)
  922.         x--;
  923.     return ((SBYTE) x);
  924. }
  925. MODULE SBYTE ypixeltosquare(SWORD y)
  926. {   y = ((y - STARTYPIXEL) / SQUAREY) - TOPGAP;
  927.     if (y < 0)
  928.         y--;
  929.     return ((SBYTE) y);
  930. }
  931.  
  932. MODULE void levelappend(void)
  933. {   UBYTE oldlevel;
  934.  
  935.     if (levels < MAXLEVELS)
  936.     {   oldlevel = level;
  937.         level = ++levels;
  938.         newfield();
  939.         level = oldlevel;
  940.         saylevel(WHITE);
  941. }   }
  942. MODULE void leveldelete(void)
  943. {   SBYTE i;
  944.  
  945.     /* pull boards */
  946.  
  947.     if (levels > 1)
  948.     {   if (level < levels)
  949.         for (i = level; i < levels; i++)
  950.             copyfield(i + 1, i);
  951.         else
  952.             level--;
  953.         levels--;
  954.         saylevel(WHITE);
  955.         turborender();
  956. }   }
  957. MODULE void levelerase(void)
  958. {   newfield();
  959.     turborender();
  960. }
  961. MODULE void levelinsert(void)
  962. {   UBYTE i;
  963.  
  964.     /* push boards */
  965.  
  966.     if (levels < MAXLEVELS)
  967.     {   for (i = levels; i >= level; i--)
  968.             copyfield(i, i + 1);
  969.         levels++;
  970.         saylevel(WHITE);
  971.         newfield();
  972.         turborender();
  973. }   }
  974. MODULE void copyfield(UBYTE source, UBYTE destination)
  975. {   SBYTE x, y;
  976.  
  977.     for (x = 0; x <= MINFIELDX; x++)
  978.         for (y = 0; y <= MINFIELDY; y++)
  979.             board[destination][x][y] = board[source][x][y];
  980.     startx[destination] = startx[source];
  981.     starty[destination] = starty[source];
  982. }
  983. MODULE SBYTE fexwrap(SBYTE x)
  984. {   if (x < 0)
  985.         x += MINFIELDX + 1;
  986.     elif (x > MINFIELDX)
  987.         x -= MINFIELDX + 1;
  988.     return(x);
  989. }
  990. MODULE SBYTE feywrap(SBYTE y)
  991. {   if (y < 0)
  992.         y += MINFIELDY + 1;
  993.     elif (y > MINFIELDY)
  994.         y -= MINFIELDY + 1;
  995.     return(y);
  996. }
  997.